﻿using Chaos;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;

public class SimpleMeshResLodPickUp : EditorWindow
{
    [MenuItem("Tools/资源提取3")]
    public static void OpenWindow()
    {
        var window = GetWindow<SimpleMeshResLodPickUp>(true, "资源提取", true);
        window.minSize = window.maxSize = new Vector2(600, 460);
    }

    private static SimpleMeshResLodPickUp GetWnd()
    {
        SimpleMeshResLodPickUp window = GetWindow<SimpleMeshResLodPickUp>(true, "资源提取", true);
        window.minSize = window.maxSize = new Vector2(600, 460);

        return window;
    }


    static private string rootDir;
    [MenuItem("Assets/模型/Mesh百分比提取")]
    static public void MenuItem_Load1()
    {
        SimpleMeshResLodPickUp window = GetWnd();
    }

    const float BUTTON_WIDTH = 120;

    string mDataPath = "Assets/Editor/ResLodPickUpData.asset";

    SimpleMeshResLodPickUpData mCurrentData;
    int mSleIndex = 0;
    bool mInited = false;

    public void InitData()
    {
        if (mInited)
            return;

        mInited = true;
            if (mCurrentData == null)
                mCurrentData = AssetDatabase.LoadAssetAtPath<SimpleMeshResLodPickUpData>(mDataPath);

            if(mCurrentData == null || mCurrentData.Name.Count == 0)
            {
                mCurrentData = ScriptableObject.CreateInstance<SimpleMeshResLodPickUpData>();

                mCurrentData.Name = new List<string>(){ "default"};
                mCurrentData.PickTexure = new List<bool>(){ false};
                mCurrentData.TexSize = new List<E_TexSize>() { E_TexSize.S512 };
                mCurrentData.MeshPer = new List<float>() { 0.9f };
                mCurrentData.ResLod = new List<E_ResLod>() { E_ResLod.Lod1 };

                mSleIndex = 0;

                SaveData();
            }
    }

    public void OnGUI()
    {
        InitData();

        int len = mCurrentData.Name.Count;
        string[] seleNames = new string[len];
        for (int i = 0; i < len;i++)
        {
            seleNames[i] = mCurrentData.Name[i];
        }

        if (mSleIndex >= len)
            mSleIndex = len - 1;

        mSleIndex = EditorGUILayout.Popup("方案:", mSleIndex, seleNames);
        mCurrentData.Name[mSleIndex] = EditorGUILayout.TextField("方案名字:", mCurrentData.Name[mSleIndex]);
        mCurrentData.ResLod[mSleIndex] = (E_ResLod)EditorGUILayout.EnumPopup("LOD等级:", mCurrentData.ResLod[mSleIndex]);

        EditorGUILayout.LabelField(GStringBuilder.Contact("     生成的资源目录为:Assets/ResLod/", mCurrentData.ResLod[mSleIndex]));
        mCurrentData.PickTexure[mSleIndex] = EditorGUILayout.Toggle("提取图片:", mCurrentData.PickTexure[mSleIndex]);
      
        if (mCurrentData.PickTexure[mSleIndex])
        {
            mCurrentData.TexSize[mSleIndex] = (E_TexSize)EditorGUILayout.EnumPopup("      尺寸:", mCurrentData.TexSize[mSleIndex]);
        }

        mCurrentData.MeshPer[mSleIndex] = EditorGUILayout.FloatField("网格百分比:", mCurrentData.MeshPer[mSleIndex]);

        using (new GUILayout.HorizontalScope())
        {
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("执行", GUILayout.Width(BUTTON_WIDTH)))
            {
                MenuItem_SetSngSimpleMeshByPer(mCurrentData.MeshPer[mSleIndex], (int)mCurrentData.ResLod[mSleIndex]);
            }

            if (GUILayout.Button("保存方案", GUILayout.Width(BUTTON_WIDTH)))
            {
                SaveData();
            }

            if (GUILayout.Button("添加方案", GUILayout.Width(BUTTON_WIDTH)))
            {
                AddData();
            }

            if (GUILayout.Button("删除方案", GUILayout.Width(BUTTON_WIDTH)))
            {
                DelData();
            }
        }
    }

    void AddData()
    {
        SimpleMeshResLodPickUpData newData = new SimpleMeshResLodPickUpData();

        mCurrentData.Name.Add("default" + mCurrentData.Name.Count);
        mCurrentData.PickTexure.Add(false);
        mCurrentData.TexSize.Add(E_TexSize.S512);
        mCurrentData.MeshPer.Add(0.9f);
        mCurrentData.ResLod.Add(E_ResLod.Lod1);

        AssetDatabase.ImportAsset(mDataPath);
    }

    void DelData()
    {
        int cnt = mCurrentData.Name.Count;

        if(cnt == 1)
        {
            EditorUtility.DisplayDialog("提醒","只有一个方案不可删除","取消");
            return;
        }

        mSleIndex = 0;
        mCurrentData.Name.RemoveAt(mSleIndex);
        mCurrentData.PickTexure.RemoveAt(mSleIndex);
        mCurrentData.TexSize.RemoveAt(mSleIndex);
        mCurrentData.MeshPer.RemoveAt(mSleIndex);
        mCurrentData.ResLod.RemoveAt(mSleIndex);

        SaveData();
    }

    void SaveData()
    {
        SimpleMeshResLodPickUpData newD = mCurrentData.Clone();

        if (File.Exists(mDataPath))
            AssetDatabase.DeleteAsset(mDataPath);

        if (!File.Exists(mDataPath))
            AssetDatabase.CreateAsset(newD, mDataPath);

        AssetDatabase.ImportAsset(mDataPath);
    }

    public void MenuItem_SetSngSimpleMeshByPer(float per,int resLod = 1)
    {
        if (Selection.assetGUIDs.Length > 0)
        {
            int cnt = Selection.assetGUIDs.Length;
            for (int i = 0; i < cnt; i++)
            {
                string path = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[i]);

                if (!System.IO.Directory.Exists(path))
                {
                    SetSimpleMeshAndComputeByPath(path, per, true, resLod);

                }
                else
                {
                    string dirPath = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[i]);

                    string[] files = Directory.GetFiles(dirPath, "*.*",SearchOption.AllDirectories);
                    int fnt = files.Length;
                    for(int fi = 0; fi < fnt;fi++)
                    {
                        if (files[fi].EndsWith("*.meta"))
                            continue;

                        SetSimpleMeshAndComputeByPath(files[fi], per, true, resLod);
                    }
                }
            }

            AssetDatabase.SaveAssets();
        }
    }

    public void SetSimpleMeshAndCompute(int resLod = 1)
    {
        string[] files = System.IO.Directory.GetFiles(rootDir, "*.prefab", System.IO.SearchOption.AllDirectories);


        int count = files.Length;

        for (int i = 0; i < count; i++)
        {
            var path = files[i];

            SetSimpleMeshAndComputeByPath(path,1f,false,resLod);
        }

        AssetDatabase.SaveAssets();
        EditorUtility.ClearProgressBar();
    }

    public void SetSimpleMeshAndComputeByPath(string path, float VertexAmount = 0.55f, bool clearMeshSimple = false,int resLod = 1)
    {
        if (path.EndsWith(".meta") || !path.EndsWith(".prefab"))
            return;

        string resLodLab = "ResLod/" + resLod;
        string newPath = path.Replace("\\", "/");
        newPath = newPath.Replace("Assets/", "Assets/" + resLodLab+"/");

        string prefabName = System.IO.Path.GetFileNameWithoutExtension(path);
        GameObject orgPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);

        GameObject prefab = GameObject.Instantiate(orgPrefab);
        prefab.name = prefabName;
        string driPre = Path.GetDirectoryName(newPath);
        if (!Directory.Exists(driPre))
            Directory.CreateDirectory(driPre);
        if (File.Exists(newPath))
            AssetDatabase.DeleteAsset(newPath);
        PrefabUtility.SaveAsPrefabAsset(prefab, newPath);

        //无须生成新的网格
        if(VertexAmount == 1f)
        {
            CreateTextrue(path, mCurrentData.TexSize[mSleIndex], mCurrentData.ResLod[mSleIndex], true);
            return;
        }

        prefab = AssetDatabase.LoadAssetAtPath<GameObject>(newPath);

        bool isContinue = false;

        SkinnedMeshRenderer[] skinMs = prefab.GetComponentsInChildren<SkinnedMeshRenderer>();
        int snt = skinMs.Length;
        for (int s = 0; s < snt; s++)
        {
            if (skinMs[s].sharedMesh == null)
            {
                Debug.LogError("ShareMesh Have Missing = " + skinMs[s].name + ":" + path);
                isContinue = true;
            }
            else if (skinMs[s].rootBone == null)
            {
                Debug.LogError("RootBone is Missing = " + skinMs[s].name + ":" + path);
                isContinue = true;
            }
        }

        if (prefab == null || isContinue)
            return;

        MeshSimplify meshSimplify = prefab.AddComponent<MeshSimplify>();
        if (meshSimplify == null)
            meshSimplify = prefab.AddComponent<MeshSimplify>();
        meshSimplify._meshSimplifier = meshSimplify.gameObject.AddComponent<Simplifier>();
        meshSimplify.VertexAmount = VertexAmount;

        meshSimplify.SimplifiedMesh = MeshSimplify.CreateNewEmptyMesh(meshSimplify);


        Renderer[] mesFiles = prefab.GetComponentsInChildren<Renderer>();
        MeshFilter[] mesFiles1 = prefab.GetComponentsInChildren<MeshFilter>();

        int cnt = mesFiles.Length > 0 ? mesFiles.Length : mesFiles1.Length;
        //MeshSimplify[] meshSList = prefab.GetComponentsInChildren<MeshSimplify>();
        MeshSimplify[] meshSList = new MeshSimplify[cnt];

        for (int i = 0; i < cnt; i++)
        {
            if(mesFiles.Length > 0)
            {
                meshSList[i] = mesFiles[i].gameObject.GetComponent<MeshSimplify>();
                if (meshSList[i] == null)
                    meshSList[i] = mesFiles[i].gameObject.AddComponent<MeshSimplify>();
            }
            else if (mesFiles1.Length > 0)
            {
                meshSList[i] = mesFiles1[i].gameObject.GetComponent<MeshSimplify>();
                if (meshSList[i] == null)
                    meshSList[i] = mesFiles1[i].gameObject.AddComponent<MeshSimplify>();
            }

            meshSList[i]._meshSimplifier = meshSList[i].gameObject.AddComponent<Simplifier>();
            meshSList[i].MeshSimplifyRoot = meshSList[i].gameObject != prefab ? meshSimplify : null;
            meshSList[i]._overrideRootSettings = false;
            meshSList[i].SimplifiedMesh = MeshSimplify.CreateNewEmptyMesh(meshSList[i]);
        }

        meshSimplify.ComputeData(meshSimplify.MeshSimplifyRoot == null, Progress);
        meshSimplify.ComputeMesh(meshSimplify.MeshSimplifyRoot == null, Progress);
        SimpleMeshUtil.DoSaveMeshAssets(meshSimplify, clearMeshSimple,false);

        GameObject.DestroyImmediate(GameObject.Find(prefabName));

        if(mCurrentData.PickTexure[mSleIndex])
            CreateTextrue(path, mCurrentData.TexSize[mSleIndex], mCurrentData.ResLod[mSleIndex], false);
    }

    static public void DelSimpleMesh()
    {
        string[] files = System.IO.Directory.GetFiles(rootDir, "*.prefab", System.IO.SearchOption.AllDirectories);


        int count = files.Length;

        for (int i = 0; i < count; i++)
        {
            var path = files[i];

            float per = (i + 1) * 1.0f / count * 1.0f;
            EditorUtility.DisplayProgressBar("正在删除SimpleMesh", (i + 1) + "/" + count, per);

            if (path.EndsWith(".meta"))
                continue;

            GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
            GameObject newPrefab = GameObject.Instantiate(prefab);
            newPrefab.name = prefab.name;

            MeshSimplify[] skinMs = newPrefab.GetComponentsInChildren<MeshSimplify>();
            int snt = skinMs.Length;
            for (int s = 0; s < snt; s++)
            {
                GameObject.DestroyImmediate(skinMs[s]);
            }

            PrefabUtility.SaveAsPrefabAsset(newPrefab, path);
            GameObject.DestroyImmediate(newPrefab);
        }

        AssetDatabase.SaveAssets();
        EditorUtility.ClearProgressBar();
    }

    static void Progress(string strTitle, string strMessage, float fT)
    {
        int nPercent = Mathf.RoundToInt(fT * 100.0f);
    }

    //====================================================================
    void CreateTextrue(string path, E_TexSize size, E_ResLod resLod, bool isDel = false)
    {
        int cSize = (int)size;
        string[] deps = AssetDatabase.GetDependencies(path);

        string parentPath = GStringBuilder.Contact("Assets/ResLod/", (int)resLod,"/");

        List<string> applyPathList = new List<string>() { path.Replace("Assets/", parentPath)};

        int len = deps.Length;
        for(int i = 0; i < len;i++)
        {
            string itemPath = deps[i];
            string toPath = itemPath.Replace("Assets/", parentPath);

            if (File.Exists(toPath))
                continue;

            if(itemPath.EndsWith(".mat"))
            {
                CreateDir(toPath);
                AssetDatabase.CopyAsset(itemPath, toPath);
                applyPathList.Add(toPath);
                continue;
            }

            TextureImporter txImp = AssetImporter.GetAtPath(itemPath) as TextureImporter;

            if (txImp == null)
                continue;

            if (isDel)
            {
                if (File.Exists(toPath))
                    AssetDatabase.DeleteAsset(toPath);
                continue;
            }

            CreateDir(toPath);

            AssetDatabase.CopyAsset(itemPath, toPath);

            AssetDatabase.ImportAsset(toPath);

            TextureImporter newImp = AssetImporter.GetAtPath(toPath) as TextureImporter;
            SetTextureSize(txImp, newImp, size, "Android",false);
            SetTextureSize(txImp, newImp, size,"iPhone",false);
            SetTextureSize(txImp, newImp, size,"Standalone",false);

            newImp.SaveAndReimport();

            applyPathList.Add(toPath);
        }

        len = applyPathList.Count;
        for (int i = 0; i < len; i++)
        {
            string toPath = applyPathList[i];

            ApplySngPath(toPath);
        }
    }

    void CreateDir(string path)
    {
        string dir = Path.GetDirectoryName(path);
        if (!Directory.Exists(dir))
            Directory.CreateDirectory(dir);
    }

    void SetTextureSize(TextureImporter orgImp,TextureImporter imp, E_TexSize size,string platm = "Android",bool save = true)
    {
        TextureImporterPlatformSettings format = imp.GetPlatformTextureSettings(platm);
        TextureImporterPlatformSettings orgFormat = orgImp.GetPlatformTextureSettings(platm);

        format.allowsAlphaSplitting = orgImp.allowAlphaSplitting;
        format.overridden = orgFormat.overridden;
        format.maxTextureSize = GetTextureSize(size);

        imp.SetPlatformTextureSettings(format);

        if(save)
            imp.SaveAndReimport();
    }

    int GetTextureSize(E_TexSize size)
    {
        switch (size)
        {
            case E_TexSize.S16: return 16;
            case E_TexSize.S32: return 32;
            case E_TexSize.S64: return 64;
            case E_TexSize.S128: return 128;
            case E_TexSize.S256: return 256;
            case E_TexSize.S512: return 512;
            case E_TexSize.S1024: return 1024;
        }

        return 0;
    }


    void ApplySngPath(string checkPath)
    {
        AssetImporter imp = AssetImporter.GetAtPath(checkPath);

        if (imp as TextureImporter != null)
            return;

        string[] lines = File.ReadAllLines(checkPath);
        int cnt = lines.Length;
        for (int i = 0; i < cnt; i++)
        {
            string lineStr = lines[i];
            int index = lineStr.IndexOf("guid");

            if (index == -1 || index == 0)
                continue;

            string guidStr = lineStr.Substring(index + 6);
            index = guidStr.IndexOf(",");
            guidStr = guidStr.Substring(0, index);

            string guidPath = AssetDatabase.GUIDToAssetPath(guidStr);
            string resLodLab = "Assets/ResLod/" + (int)mCurrentData.ResLod[mSleIndex] + "/";
            string resLoadPath = guidPath.Replace("\\", "/");
            resLoadPath = resLoadPath.Replace("Assets/", resLodLab);

            string newGuid = AssetDatabase.AssetPathToGUID(resLoadPath);

            if (string.IsNullOrEmpty(newGuid))
                continue;

            lineStr = lineStr.Replace(guidStr, newGuid);
            lines[i] = lineStr;
        }

        AssetDatabase.DeleteAsset(checkPath);
        File.WriteAllLines(checkPath, lines);

        AssetDatabase.ImportAsset(checkPath);
    }
}
